﻿using System;
using CID.Domain.Audit;
using CID.Domain.Exceptions;
using CID.Domain.Infrastructure;
using CID.Tests.Support;
using NUnit.Framework;

namespace CID.Domain.Tests.Audit
{
    [TestFixture]
    public class ParameterDeploymentLogTests : BaseFunctionalTests
    {
        #region ParameterDeploymentLogImplementation
        private class ParameterDeploymentLogImplementation : ParameterDeploymentLog
        {
            public ParameterDeploymentLogImplementation(IVersionDeploymentLog versionDeploymentLog, IParameterValue parameter)
                : base(versionDeploymentLog, parameter)
            { 
            }
        }
        #endregion

        protected const string StringValue = "String Value";
        protected const int IntegerValue = 321;
        protected const decimal DecimalValue = 3.21m;
        protected static readonly DateTime DateTimeValue = DateTime.Now;
        protected const bool BooleanValue = false;
        protected static readonly Guid UniqueIdentifierValue = Guid.NewGuid();
        protected const string XmlValueAsString = "<?xml version=\"1.0\"?><configuration><connectionStrings><add name=\"\" connectionString=\"\" providerName=\"System.Data.SqlClient\" /></connectionStrings></configuration>";

        private const string ParameterName = "parameterName";

        private static IParameterValue CreateParameterValue(ParameterType type)
        {
            var parameter = Infrastructure.StubsBuilder.BuildParameterStub(type);
            parameter.Name = ParameterName;
            return Infrastructure.StubsBuilder.BuildParameterValueStub(parameter: parameter);
        }

        private IVersionDeploymentLog versionDeploymentLog;
        public override void SetUp()
        {
            base.SetUp();

            versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
        }

        [Test]
        public void CreateParameterDeploymentLog_ForStringParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.String);
            parameterValue.StringValue = StringValue;

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(ParameterValueSerializer.Serialize(StringValue), parameterDeploymentLog.ParameterValue);
        }

        [Test]
        public void CreateParameterDeploymentLog_ForIntegerParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.Integer);
            parameterValue.IntegerValue = IntegerValue;

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(ParameterValueSerializer.Serialize(IntegerValue), parameterDeploymentLog.ParameterValue);
        }

        [Test]
        public void CreateParameterDeploymentLog_ForDecimalParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.Decimal);
            parameterValue.DecimalValue = DecimalValue;

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(ParameterValueSerializer.Serialize(DecimalValue), parameterDeploymentLog.ParameterValue);
        }

        [Test]
        public void CreateParameterDeploymentLog_ForDateTimeParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.DateTime);
            parameterValue.DateTimeValue = DateTimeValue;

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(ParameterValueSerializer.Serialize(DateTimeValue), parameterDeploymentLog.ParameterValue);
        }

        [Test]
        public void CreateParameterDeploymentLog_ForBooleanParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.Boolean);
            parameterValue.BooleanValue = BooleanValue;

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(ParameterValueSerializer.Serialize(BooleanValue), parameterDeploymentLog.ParameterValue);
        }

        [Test]
        public void CreateParameterDeploymentLog_ForUniqueIdentifierParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.UniqueIdentifier);
            parameterValue.UniqueIdentifierValue = UniqueIdentifierValue;

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(ParameterValueSerializer.Serialize(UniqueIdentifierValue), parameterDeploymentLog.ParameterValue);
        }

        [Test]
        public void CreateParameterDeploymentLog_ForXmlParameterValue()
        {
            var parameterValue = CreateParameterValue(ParameterType.Xml);
            parameterValue.XmlValue = new System.Xml.XmlDocument();
            parameterValue.XmlValue.LoadXml(XmlValueAsString);

            var parameterDeploymentLog = new ParameterDeploymentLogImplementation(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, parameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(ParameterName, parameterDeploymentLog.ParameterName);
            Assert.AreEqual(XmlValueAsString, parameterDeploymentLog.ParameterValue);
        }

        #region ActivationParameterDeploymentLog
        [Test]
        public void CreateActivationParameterDeploymentLog_ValidTemplate_ShouldSucceed()
        {
            var versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
            var parameterValue = Infrastructure.StubsBuilder.BuildParameterValueStub(Infrastructure.StubsBuilder.BuildParameterStub(template: Infrastructure.StubsBuilder.BuildActivationTemplateStub()));

            var activationParameterDeploymentLog = new ActivationParameterDeploymentLog(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, activationParameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(parameterValue.Parameter.Name, activationParameterDeploymentLog.ParameterName);
        }

        [Test, ExpectedException(typeof(InvalidParameterAssignmentTemplateException))]
        public void CreateActivationParameterDeploymentLog_InvalidTemplate_ShouldThrowException()
        {
            var versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
            var parameterValue = Infrastructure.StubsBuilder.BuildParameterValueStub(Infrastructure.StubsBuilder.BuildParameterStub(template: Infrastructure.StubsBuilder.BuildDeactivationTemplateStub()));

            var activationParameterDeploymentLog = new ActivationParameterDeploymentLog(versionDeploymentLog, parameterValue);
        }
        #endregion

        #region DeactivationParameterDeploymentLog
        [Test]
        public void CreateDeactivationParameterDeploymentLog_ValidTemplate_ShouldSucceed()
        {
            var versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
            var parameterValue = Infrastructure.StubsBuilder.BuildParameterValueStub(Infrastructure.StubsBuilder.BuildParameterStub(template: Infrastructure.StubsBuilder.BuildDeactivationTemplateStub()));

            var activationParameterDeploymentLog = new DeactivationParameterDeploymentLog(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, activationParameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(parameterValue.Parameter.Name, activationParameterDeploymentLog.ParameterName);
        }

        [Test, ExpectedException(typeof(InvalidParameterAssignmentTemplateException))]
        public void CreateDeactivationParameterDeploymentLog_InvalidTemplate_ShouldThrowException()
        {
            var versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
            var parameterValue = Infrastructure.StubsBuilder.BuildParameterValueStub(Infrastructure.StubsBuilder.BuildParameterStub(template: Infrastructure.StubsBuilder.BuildDeploymentTemplateStub()));

            var activationParameterDeploymentLog = new DeactivationParameterDeploymentLog(versionDeploymentLog, parameterValue);
        }
        #endregion

        #region DeactivationParameterDeploymentLog
        [Test]
        public void CreateDeploymentParameterDeploymentLog_ValidTemplate_ShouldSucceed()
        {
            var versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
            var parameterValue = Infrastructure.StubsBuilder.BuildParameterValueStub(Infrastructure.StubsBuilder.BuildParameterStub(template: Infrastructure.StubsBuilder.BuildDeploymentTemplateStub()));

            var activationParameterDeploymentLog = new DeploymentParameterDeploymentLog(versionDeploymentLog, parameterValue);

            Assert.AreEqual(versionDeploymentLog, activationParameterDeploymentLog.VersionDeploymentLog);
            Assert.AreEqual(parameterValue.Parameter.Name, activationParameterDeploymentLog.ParameterName);
        }

        [Test, ExpectedException(typeof(InvalidParameterAssignmentTemplateException))]
        public void CreateDeploymentParameterDeploymentLog_InvalidTemplate_ShouldThrowException()
        {
            var versionDeploymentLog = StubsBuilder.BuildVersionDeploymentLogStub();
            var parameterValue = Infrastructure.StubsBuilder.BuildParameterValueStub(Infrastructure.StubsBuilder.BuildParameterStub(template: Infrastructure.StubsBuilder.BuildActivationTemplateStub()));

            var activationParameterDeploymentLog = new DeploymentParameterDeploymentLog(versionDeploymentLog, parameterValue);
        }
        #endregion
    }
}
